package org.hiro.psi;

import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElementFactory;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.codeStyle.CodeStyleManager;
import static org.apache.commons.lang.StringUtils.uncapitalize;

public class SimpleBuildMethodBuilder<T extends SimpleBuildMethodBuilder> extends PsiMethodBuilder<SimpleBuildMethodBuilder> {
    private PsiClass classToBuild;

    public SimpleBuildMethodBuilder(PsiElementFactory elementFactory, CodeStyleManager codeStyleManager) {
        super(elementFactory, codeStyleManager);
    }

    @Override
    public PsiMethod build() {
        String returnType = classToBuild.getContainingFile().getName().split("\\.")[0];
        String objectName = uncapitalize(returnType);

        withMethodText(createBuildMethodText(returnType, objectName));
        return super.build();
    }

    private String createBuildMethodText(String returnType, String objectName) {
        String constructorText = createObjectInstantiationText(returnType, objectName);
        return "public " + returnType + " build() { " +
                constructorText +
                "for (Map.Entry<String, Object> entry : values.entrySet()) {" +
                getReflexiveSetText(objectName) +
                "}" +
                "return " + objectName + ";}";
    }

    private String createObjectInstantiationText(String returnType, String objectName) {
        return returnType + " " + objectName + " = newEmptyObject();";
    }

    protected String getReflexiveSetText(String objectName) {
        return "Field field = " + objectName + ".getClass().getDeclaredField(entry.getKey());" +
                "field.setAccessible(true);" +
                "field.set(" + objectName + ", entry.getValue());";
    }

    public T withClassToBuild(PsiClass classToBuild) {
        this.classToBuild = classToBuild;
        return (T) this;
    }
}
